package com.jfire.socket.socketserver.bus;

import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
import sun.misc.Unsafe;
import com.jfire.baseutil.collection.ByteBufferPool;
import com.jfire.baseutil.collection.ByteCache;
import com.jfire.baseutil.collection.ByteCachePool;
import com.jfire.baseutil.reflect.ReflectUtil;
import com.jfire.socket.socketserver.util.HeadFactory;

@SuppressWarnings("restriction")
public class Message
{
    /** 报文数据体 */
    private ByteCache         businessData;
    /** 报文所在通道信息 */
    private ServerChannelInfo channelInfo;
    /** 报文发送方 */
    private byte              actionType;
    /** 报文命令 */
    private byte              command;
    /** 消息写出使用过的buffer */
    private ByteBuffer        writeBuffer;
    private int               writed        = 0;
    private volatile byte     requestResult = BusinessCommand.REQUEST_SUCCESS;
    private volatile boolean  flowFinish    = false;
    private HeadFactory       headFactory;
    private static Unsafe     unsafe        = ReflectUtil.getUnsafe();
    private static long       writedOffset;
    static
    {
        try
        {
            Field field = Message.class.getDeclaredField("writed");
            writedOffset = unsafe.objectFieldOffset(field);
        }
        catch (NoSuchFieldException | SecurityException e)
        {
            e.printStackTrace();
        }
        
    }
    
    /**
     * 使用初始化参数对消息进行初始化
     * 
     * @param headFactory 报文头生成工厂
     * @param actionType 发送类型
     * @param command 报文命令
     * @param businessData 报文数据
     * @param serverChannelInfo 所在通道
     */
    public Message(HeadFactory headFactory, byte actionType, byte command, ByteCache businessData, ServerChannelInfo serverChannelInfo)
    {
        this.actionType = actionType;
        this.headFactory = headFactory;
        this.channelInfo = serverChannelInfo;
        this.command = command;
        this.businessData = businessData;
    }
    
    public ByteCache getBusinessData()
    {
        return businessData;
    }
    
    public ServerChannelInfo getChannelInfo()
    {
        return channelInfo;
    }
    
    public byte getCommand()
    {
        return command;
    }
    
    public ByteBuffer getWriteBuffer()
    {
        return writeBuffer;
    }
    
    public void tryWrite()
    {
        if (flowFinish == false || writed == 1)
        {
            return;
        }
        Queue<Message> sendQueue = channelInfo.getSendQueue();
        if (sendQueue.peek() == this)
        {
            //争夺到将message写出的资格的线程执行后续的写出操作
            if (unsafe.compareAndSwapInt(this, writedOffset, 0, 1))
            {
                writeBuffer = ByteBufferPool.getBuffer(businessData.getCount() + 8);
                headFactory.putHeadInBuffer(writeBuffer, command, businessData.getCount());
                writeBuffer.put(actionType).put(command).put(requestResult);
                writeBuffer.putInt(businessData.getCount());
                writeBuffer.put(businessData.getDirectArray(), 0, businessData.getCount());
                writeBuffer.flip();
                channelInfo.getSocketChannel().write(writeBuffer, 10, TimeUnit.SECONDS, this, channelInfo.getMessageWriteCompleteHandler());
                ByteCachePool.returnCache(businessData);
            }
        }
    }
    
    /**
     * 当前流程已经完成
     */
    public void flowFinish()
    {
        flowFinish = true;
    }
    
    public void requestFail()
    {
        requestResult = BusinessCommand.REQUEST_FAIL;
    }
}
